package com.antoco.controlcenter.comm.message;

import com.antoco.controlcenter.comm.message.NciMessage;
import com.antoco.controlcenter.utils.CRC16;

import java.util.ArrayList;
import java.util.List;

public class RobotMessageBase {
    protected int HeaderOffset = 0;
    protected int HeaderLength = 1;

    protected int VersionOffset = 1;
    protected int VersionLength = 1;

    protected int AddressOffset = 2;
    protected int AddressLength = 2;

    protected int DataBufferOffset = 4;
    protected int DataBufferLength = 12;

    protected int NciOffset = 16;
    protected int NciLength = 32;

    protected int CrcOffset = 48;
    protected int CrcLength = 2;

    protected int TempOffset = 50;
    protected int TempLength = 2;
    protected int _nciSeek = 0;
    protected int _nciNum = 4;
    protected byte[] ByteArray;

    public RobotMessageBase(int dataBufferLength) {
        DataBufferLength = dataBufferLength;
        OffsetInit();
        ByteArray = new byte[GetFrameLength()]; // 初始化字节数组
        FrameStructInit(); // 初始化帧结构
    }

    public RobotMessageBase(byte[] byteArray) {
        DataBufferLength = byteArray.length - (GetFrameLength() - DataBufferLength);
        OffsetInit();
        ByteArray = new byte[GetFrameLength()]; // 初始化字节数组
        System.arraycopy(byteArray, 0, ByteArray, 0, GetFrameLength());
        FrameStructInit(); // 初始化帧结构?
    }

    public byte[] GetHeader() {
        byte[] retArray = new byte[HeaderLength];
        System.arraycopy(ByteArray, HeaderOffset, retArray, 0, HeaderLength);
        return retArray;
    }

    public byte[] GetVersion() {
        byte[] retArray = new byte[VersionLength];
        System.arraycopy(ByteArray, VersionOffset, retArray, 0, VersionLength);
        return retArray;
    }

    public byte[] GetAddress() {
        byte[] retArray = new byte[AddressLength];
        System.arraycopy(ByteArray, AddressOffset, retArray, 0, AddressLength);
        return retArray;
    }

    public byte[] GetDataBuffer() {
        byte[] retArray = new byte[DataBufferLength];
        System.arraycopy(ByteArray, DataBufferOffset, retArray, 0, DataBufferLength);
        return retArray;
    }

    public byte[] GetNci() {
        byte[] retArray = new byte[NciLength];
        System.arraycopy(ByteArray, NciOffset, retArray, 0, NciLength);
        return retArray;
    }

    public byte[] GetCrc() {
        byte[] retArray = new byte[CrcLength];
        System.arraycopy(ByteArray, CrcOffset, retArray, 0, CrcLength);
        return retArray;
    }

    public byte[] GetTemp() {
        byte[] retArray = new byte[TempLength];
        System.arraycopy(ByteArray, TempOffset, retArray, 0, TempLength);
        return retArray;
    }

    public byte[] GetByteArray() {
        return ByteArray;
    }

    public int GetFrameLength() {
        return HeaderLength + VersionLength + AddressLength + DataBufferLength + NciLength + CrcLength + TempLength;
    }

    protected void SetHeader(byte[] header) {
        System.arraycopy(header, 0, ByteArray, HeaderOffset, HeaderLength);
    }

    public void SetVersion(byte[] version) {
        System.arraycopy(version, 0, ByteArray, VersionOffset, VersionLength);
    }

    public void SetAddress(byte[] address) {
        System.arraycopy(address, 0, ByteArray, AddressOffset, AddressLength);
    }

    public void SetDataBuffer(byte[] dataBuffer) {
        System.arraycopy(dataBuffer, 0, ByteArray, DataBufferOffset, DataBufferLength);
    }

    public void SetCrc(byte[] crc) {
        System.arraycopy(crc, 0, ByteArray, CrcOffset, CrcLength);
    }

    protected void SetTemp(byte[] temp) {
        System.arraycopy(temp, 0, ByteArray, TempOffset, TempLength);
    }

    public void AddNci(NciMessage nci) {
        if (_nciSeek < _nciNum) {
            System.arraycopy(nci.GetByteArray(), 0, ByteArray, NciOffset + (_nciSeek++ * 8), 8);
        }
    }

    public List<NciMessage> GetNciList() {
        List<NciMessage> nciList = new ArrayList<NciMessage>();
        for (int i = 0; i < 4; i++) {
            byte[] tempNci = new byte[8];
            System.arraycopy(ByteArray, NciOffset + (i * 8), tempNci, 0, 8);
            NciMessage nci = new NciMessage(tempNci);
            if (nci.GetCmd() != 0x00) {
                nciList.add(nci);
            }
        }
        return nciList;
    }

    public byte[] CalcCrc() {
        // 需要校验的长度
        int checkLen = HeaderLength + VersionLength + AddressLength + DataBufferLength + NciLength;
        byte[] temp = new byte[checkLen];
        System.arraycopy(ByteArray, 0, temp, 0, checkLen);
        byte[] _crc = CRC16.crc16Bytes(temp);
        return _crc;
    }

    public boolean CheckCrc() {
        byte[] _crc = CalcCrc();
        return _crc[0] == ByteArray[CrcOffset + 1] && _crc[1] == ByteArray[CrcOffset];
    }

    // 帧结构偏移重置
    private void OffsetInit() {
        HeaderOffset = 0;
        VersionOffset = HeaderOffset + HeaderLength;
        AddressOffset = VersionOffset + VersionLength;
        DataBufferOffset = AddressOffset + AddressLength;
        NciOffset = DataBufferOffset + DataBufferLength;
        CrcOffset = NciOffset + NciLength;
        TempOffset = CrcOffset + CrcLength;
    }

    // 帧结构重置
    private void FrameStructInit() {
        SetHeader(new byte[] { 0x55 });
        SetTemp(new byte[] { (byte) 0xAA, (byte) 0xAA });
    }

    @Override
    public String toString() {
        return String.format(
                "RobotMessage : Header = %s, Version = %s, Address = %s, DataBuffer = %s, Nci = %s, Crc = %s, Temp = %s",
                GetHeader(), GetVersion(), GetAddress(), GetDataBuffer(), GetNci(), GetCrc(), GetTemp());
    }
}